﻿#include "Mainwindow.h"
#include <QDebug>

Mainwindow::Mainwindow(QWidget* parent)
	:QWidget(parent)
	,ui(new Ui::Mainwindow)
{
	ui->setupUi(this);

	qInfo() << "sequential> " << isSequential;


	init();


	//给搜索输入框设置事件过滤处理：		方便来使用快捷键搜索；
	ui->searchEdit->installEventFilter(this);
}

Mainwindow::~Mainwindow()
{
	delete ui;
}

//总初始化													over
void Mainwindow::init()
{
	//布局初始化：
	layoutinit();

	//数据库初始化：
	sqlinit();

	//播放初始化：
	playerinit();

	//本地音乐初始化：
	local_music_init();
	
}

//布局初始化													over
void Mainwindow::layoutinit()
{
	//禁止窗口改变尺寸大小：
	this->setFixedSize(this->geometry().size());
	//去掉标题任务栏：
	this->setWindowFlag(Qt::FramelessWindowHint);

	//去掉边框和状态栏：
	this->setWindowFlag(Qt::FramelessWindowHint);
	//去掉后，窗口就不能正常移动了，所以最方便的方法就是手动添加个类来调用实现：
	QObject::installEventFilter(new eventFilterObject(this));

	//设置程序图标：
	this->setWindowIcon(QIcon("./assets/images/a.ico"));




	//给lyricsEdit添加默认文本：
	ui->lyricsEdit->setText("先找想听的歌啊");
}

//数据库初始化：												over
void Mainwindow::sqlinit()
{
	//数据库连接：
	//1.判断数据库连接是否存在，存在就连接，不存在就添加：
	if (QSqlDatabase::contains("sql_default_connection"))
	{
		//根据数据库默认连接名称得到连接：
		database = QSqlDatabase::database("sql_default_connection");
	}
	else
	{
		//添加数据库，得到该数据库的默认：
		database = QSqlDatabase::addDatabase("QSQLITE");
		//设置数据库文件名称：
		database.setDatabaseName("mp3litedatabase.db");

	}

	//2.打开数据库，打开标识（QSqlQuery）类：
	if (!database.open())
	{
		//弹出消息框报错：
		QMessageBox::critical(0, QObject::tr("open Data Error."), database.lastError().text());
	}
	else
	{
		//3.定义query对象，得到打开的数据库标识：
		QSqlQuery query;

		QString sql = "create table if not exists searchlist(id integer,songname text,artist text,album_id text,hash text);";
		if (!query.exec(sql))
		{
			QMessageBox::critical(0, QObject::tr("create searchlist Error."), database.lastError().text());

		}

		//歌曲历史表：
		sql = "create table if not exists historysong(id integer primary key autoincrement,songname text,artist text,album_id text,hash text);";
		if (!query.exec(sql))
		{
			QMessageBox::critical(0, QObject::tr("create historysong Error."), database.lastError().text());

		}


		//查询历史数据表中的插入歌曲的数据：
		sql = "select * from historysong;";
		if (!query.exec(sql))
		{
			QMessageBox::critical(0, QObject::tr("select historysong Error."), database.lastError().text());

		}
		//添加到listwidget中：
		while (query.next())
		{
			QString songname, artist;
			QSqlRecord record = query.record();
			int ablumkey = record.indexOf("songname");
			int hashkey = record.indexOf("artist");
			songname = query.value(ablumkey).toString();
			artist = query.value(hashkey).toString();

			QString strshow = songname + "." + artist;
			//添加：
			QListWidgetItem* item = new QListWidgetItem(strshow);
			ui->history->addItem(item);

			qInfo() << songname << artist;

		}
	}
}

//播放器初始化：
void Mainwindow::playerinit()
{
	player = new QMediaPlayer;
	audiooutput = new QAudioOutput;
	player->setAudioOutput(audiooutput);

	//设置音量滑动条：
	ui->volumeSlider->setValue(100);

	//设置音量：
	audiooutput->setVolume(30);

	//连接	更新播放进度条和播放时间：
	QObject::connect(player, &QMediaPlayer::positionChanged, this, &Mainwindow::updateDuration);
	QObject::connect(player, &QMediaPlayer::positionChanged, this, &Mainwindow::onPositionChanged);

	//设置歌曲播放进度条：
	QObject::connect(ui->timeSlider, &QSlider::sliderMoved, [=](int pos)
		{
			player->setPosition(pos);
		});


	//连接	显示歌词的槽函数：
	QObject::connect(this, &Mainwindow::lyricShow, this, &Mainwindow::lyricTextShow);


	//双击	搜索结果widget的项	播放当前选中的音乐：
	QObject::connect(ui->resultsList, &QListWidget::doubleClicked, this, &Mainwindow::playeSearch);
	//双击	历史widget的项	播放当前选中的音乐：
	QObject::connect(ui->history, &QListWidget::doubleClicked, this, &Mainwindow::playerhistory);

	//连接	循环播放设置：
	QObject::connect(player, &QMediaPlayer::playbackStateChanged, [&]()
		{
			if ((isLoop == true) && (isSequential = false))
			{
				if (QMediaPlayer::PlaybackState::StoppedState == player->playbackState())
				{
					player->play();
				}
			}
			else if ((isLoop == false) && (isSequential = true))
			{
				if (QMediaPlayer::PlaybackState::StoppedState == player->playbackState())
				{
					on_nextBtn_released();
				}

			}


		});
}



//音乐歌曲下载和播放：											over
void Mainwindow::downloadSong(QString album_id, QString hash)
{
	QString url = kugouDownloadApi + QString("r=play/getdata"
											 "&hash=%1&album_id=%2"
											 "&dfid=1spkkh3QKS9P0iJupz0oTy5G"
											 "&mid=de94e92794f31e9cd6ff4cb309d2baa2"
											 "&platid=4").arg(hash).arg(album_id);

	httpAccess(url);


	QByteArray JsonData;
	QEventLoop loop;

	auto d = QObject::connect(this, &Mainwindow::finish, this,[&](const QByteArray& data)
		{
			JsonData = data;
			loop.exit(1);
		});

	loop.exec();

	QObject::disconnect(d);


	//解析将要播放的音乐：
	QString music = musicAnalysis(JsonData);

	//player->setMedia(QUrl(music));
	player->setSource(QUrl(music));

	

	

	//播放音乐：
	player->play();

}
//访问HTTP网页：												over
void Mainwindow::httpAccess(QString url)
{
	//1.实例化网络请求事项：
	request = new QNetworkRequest;

	//将url网页地址存入request请求当中：
	request->setUrl(url);

	//实例化网络管理（访问）：
	manager = new QNetworkAccessManager;

	//通过get方法，上传具体的请求：
	manager->get(*request);

	//当网页回复消息时，触发finished信号，才能读取数据信息：
	QObject::connect(manager, &QNetworkAccessManager::finished, this, &Mainwindow::netReply);

}
//读取网络数据的槽函数：										over
void Mainwindow::netReply(QNetworkReply* reply)
{
	//获取响应的信息，状态码为200属于正常：
	QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
	qInfo() << status_code;

	reply->attribute(QNetworkRequest::RedirectionTargetAttribute);

	//如果没有错误	返回：
	if (QNetworkReply::NoError == reply->error())
	{
		QByteArray data = reply->readAll();
		emit finish(data);

	}
	else
	{
		qInfo() <<"netReply Error>" << reply->errorString();
	}

	reply->deleteLater();

}
//音乐的hash和album_id的值解析，使用JSON：                      over
void Mainwindow::hashJsonAnalysis(const QByteArray& JsonData)
{
	QJsonDocument docoment = QJsonDocument::fromJson(JsonData);
	if (docoment.isObject())
	{
		QJsonObject data = docoment.object();

		if (data.contains("data"))
		{
			QJsonObject objectInfo = data.value("data").toObject();
			if (objectInfo.contains("info"))
			{
				QJsonArray objectHash = objectInfo.value("info").toArray();


				for (int i = 0; i < objectHash.count(); i++)
				{
					QString songname, artist, album_id, hash;
					QJsonObject album = objectHash.at(i).toObject();


					if (album.contains("album_id"))
					{
						album_id = album.value("album_id").toString();
					}
					if (album.contains("artist"))
					{
						artist = album.value("artist").toString();
					}
					if (album.contains("songname"))
					{
						songname = album.value("songname").toString();
					}
					if (album.contains("hash"))
					{
						hash = album.value("hash").toString();
					}

					
					QSqlQuery query;
					QString sql = QString("insert into searchlist values (%1,'%2','%3','%4','%5');")
						.arg(QString::number(i)).arg(songname).arg(artist).arg(album_id).arg(hash);

					if (!query.exec(sql))
					{
						QMessageBox::critical(0, QObject::tr("insert searchlist Error."), database.lastError().text());

					}

					//将解析的音乐名称，存入listwidget	result	中：

					QString show = songname + "." + artist;
					QListWidgetItem* item = new QListWidgetItem(show);
					ui->resultsList->addItem(item);

					//qInfo() <<"hashJsonAnalysis>" << show;

				}
			}
		}
	}

	if (docoment.isArray())
	{
		qInfo() << "Array";
	}


}
//搜素的音乐数据信息JSON解析，读取出真正的音乐文件和歌词：			over
QString Mainwindow::musicAnalysis(QByteArray JsonData)
{
	QJsonDocument document = QJsonDocument::fromJson(JsonData);

	if (document.isObject())
	{
		QJsonObject data = document.object();

		if (data.contains("data"))
		{
			QJsonObject objectPLayUrl = data.value("data").toObject();

			if (objectPLayUrl.contains("lyrics"))
			{
				emit lyricShow(objectPLayUrl.value("lyrics").toString());

			}

			if (objectPLayUrl.contains("play_url"))
			{
				return objectPLayUrl.value("play_url").toString();
			}
				
		}

		if (document.isArray())
		{
			qInfo() << "Array.";
		}
	}

}



//更新播放的进度条和显示的时间的槽函数：							over
void Mainwindow::updateDuration(qint64 value)
{
	//qInfo() << "updateDuration";

	ui->timeSlider->setRange(0, player->duration());
	ui->timeSlider->setValue(value);

}
//槽函数:QMediaPlayer的position（播放时长）变化的信号槽函数		over
void Mainwindow::onPositionChanged(qint64 position)
{
	qint64 duration = player->duration();

	QString durationStr = QString("%1:%2").arg(duration / 1000 / 60 % 60,
		2, 10, QChar('0')				//重载函数，字符串宽度，进制，设置填充字符
	)
		.arg(duration / 1000 % 60,
			2, 10, QChar('0')		//重载函数，字符串宽度，进制，设置填充字符
		);
	QString posStr = QString("%1:%2").arg(position / 1000 / 60 % 60,
		2, 10, QChar('0')					//重载函数，字符串宽度，进制，设置填充字符
	)
		.arg(position / 1000 % 60,
			2, 10, QChar('0')		//重载函数，字符串宽度，进制，设置填充字符
		);

	ui->timeLab->setText(posStr + "/" + durationStr);


}

//音量调节和显示：												over
void Mainwindow::on_volumeSlider_valueChanged(int value)
{
	//qInfo() << value;
	audiooutput->setVolume(static_cast<float>(value) / ui->volumeSlider->maximum());

	ui->volumeLab->setText(QString::number(value) + "%");

}

//显示歌词的槽函数：											over
void Mainwindow::lyricTextShow(QString lyrics)
{
	//删除默认文本：
	ui->lyricsEdit->clear();


	ui->lyricsEdit->setFont(QFont("微软雅黑", 10, QFont::Bold));
	ui->lyricsEdit->setTextColor(Qt::black);
	ui->lyricsEdit->setText(lyrics);

}

//搜索音乐按钮：												over
void Mainwindow::on_searchBtn_released()
{
	//qInfo() << "搜索歌曲按钮按下";

	//点击了搜索按钮	就不再是本地音频了：	置为false：
	isLocal = false;

	//将原有的搜索列表的歌曲数据清空
	ui->resultsList->clear();

	//先清理数据库中已经存储的hash等数据：
	QSqlQuery query;
	QString sql = "delete from searchlist;";
	if (!query.exec(sql))
	{
		QMessageBox::critical(0, QObject::tr("delete searchlist Error."), database.lastError().text());

	}


	//根据用户输入的音乐名称	发起请求操作：
	QString url = kugouSearchApi + QString("format=json&keyword=%1&page=1&pagesize=20&showtype=1").arg(ui->searchEdit->text());

	//请求http：
	httpAccess(url);

	QByteArray JsonData;
	QEventLoop loop;
	auto c = QObject::connect(this, &Mainwindow::finish, [&](const QByteArray& data)
		{
			JsonData = data;
			loop.exit(1);
		});

	loop.exec();
	QObject::disconnect(c);

	//解析网页回复的数据，将搜索得到的音乐hash和album_id与列表的索引值	存放到数据库中：
	hashJsonAnalysis(JsonData);

}





//播放搜索音乐：												over
void Mainwindow::playeSearch()
{
	//获取双击的割弃对应索引，是数据库当中数据表中的id号：
	int cur_row = ui->resultsList->currentRow();
	qInfo() << "row--" << cur_row;


	if (!isLocal)		//如果不是本地音频：
	{
		
		//查询搜索数据库中数据表中存储的音乐的数据信息：
		QSqlQuery query;
		QString sql = QString("select * from searchlist where id = %1;").arg(cur_row);
		if (!query.exec(sql))
		{
			QMessageBox::critical(0, QObject::tr("select searchlist table Error."), database.lastError().text());
		}


		//将选中的音乐的数据信息存入历史数据表中：
		QString songname, artist, album_id, hash;
		while (query.next())
		{
			QSqlRecord record = query.record();

			int songnamekey = record.indexOf("songname");
			int artistkey = record.indexOf("artist");
			int album_idkey = record.indexOf("album_id");
			int hashkey = record.indexOf("hash");


			songname = query.value(songnamekey).toString();
			artist = query.value(artistkey).toString();
			album_id = query.value(album_idkey).toString();
			hash = query.value(hashkey).toString();


			sql = QString("select hash from historysong where hash = '%1';").arg(hash);
			if (!query.exec(sql))
			{
				QMessageBox::critical(0, QObject::tr("select hash from historysong Error."), database.lastError().text());
			}


			//
			if (query.next() == NULL)
			{
				sql = QString("insert into historysong values(NULL,'%1','%2','%3','%4');")
					.arg(songname).arg(artist).arg(album_id).arg(hash);
				if (!query.exec(sql))
				{
					QMessageBox::critical(0, QObject::tr("insert into historysong values Error."), database.lastError().text());
				}


				//将解析的音乐名称，保存到ListWidget history 中：
				QString show = songname + "." + artist;
				QListWidgetItem* item = new QListWidgetItem(show);
				ui->history->addItem(item);

				//qInfo() <<"playSearch>" << show;
			}
		}

		downloadSong(album_id, hash);
	}
	else           //如果是本地音频：
	{

		isHistory = false;
		qInfo() << "isHistory>" << isHistory;



		m_playList_song.setCurrentIndex(cur_row);

		auto cur_url = m_playList_song.currentUrl();

		player->setSource(cur_url);
		player->play();
	}
	

}
//播放历史音乐：												over
void Mainwindow::playerhistory()
{
	isHistory = true;
	qInfo() << "isHistory>" << isHistory;

	//获取双击哪一行的索引，其实就是数据库中的数据表中的id编号：
	row = ui->history->currentRow();
	qInfo() << "row-->" << row;


	//查询搜索数据库中的数据表的历史记录存储的音乐数据信息：
	QSqlQuery query;
	QString sql = QString("select * from historysong where id = %1;").arg(row + 1);
	if (!query.exec(sql))
	{
		QMessageBox::critical(0, QObject::tr("select * from historysong Error."), database.lastError().text());

	}


	//将选中的音乐的数据信息存入历史数据表中：
	QString album_id, hash;
	while (query.next())
	{
		QSqlRecord record = query.record();

		int album_idkey = record.indexOf("album_id");
		int hashkey = record.indexOf("hash");


		album_id = query.value(album_idkey).toString();
		hash = query.value(hashkey).toString();
	}


	downloadSong(album_id, hash);

}





//左上角按钮：
		//换肤按钮：											over
void Mainwindow::on_huanfuBtn_released()
{
	//qInfo() << "换肤按钮按下";
	QMessageBox::about(this, "about",
		"老子不想做\n");
}
		//最小化按钮：										over
void Mainwindow::on_minBtn_released()
{
	this->showMinimized();
}
		//关于按钮：											over
void Mainwindow::on_aboutBtn_released()
{
	//qInfo() << "关于按钮按下";
	QMessageBox::about(this, "about", 
		"mp3音乐搜索引擎\n"
			"by\tLeiffie\n"
			"播放器功能如下：\t\n"
			"搜索音乐歌曲功能\t\n"
			"上一曲 播放/暂停 下一曲\t\n");
}
		//关闭按钮：											over
void Mainwindow::on_closeBtn_released()
{
	//qInfo() << "关闭按钮按下";
	this->close();
}




//下面按钮和进度条：
		//循环播放按钮：
void Mainwindow::on_sequentialBtn_released()
{
	if (!isSequential)
	{
		isSequential = true;
		ui->sequentialBtn->setText("start sequential");
	}
	else
	{
		isSequential = false;
		ui->sequentialBtn->setText("end sequential");
	}

	qInfo() <<"sequential> " << isSequential;


}
		//上一曲按钮：
void Mainwindow::on_preBtn_released()
{
	//qInfo() << "上一首按钮按下";


	//设置焦点：
	this->setFocus();


	if (!isLocal)			//如果不是本地音频
	{
		row--;
		if (row <= 0)
		{
			row = ui->history->count() - 1;

		}

		//查询搜索数据库历史记录表当中存储音乐数据信息：
		QSqlQuery query;
		QString sql = QString("select * from historysong where id = %1;").arg(row + 1);
		if (!query.exec(sql))
		{
			QMessageBox::critical(0, QObject::tr("select * from history row Error."), database.lastError().text());

		}


		QString album_id, hash;
		while (query.next())
		{
			QSqlRecord record = query.record();

			int album_idkey = record.indexOf("album_id");
			int hashkey = record.indexOf("hash");


			album_id = query.value(album_idkey).toString();
			hash = query.value(hashkey).toString();
		}

		downloadSong(album_id, hash);
	}
	else
	{
		m_playList_song.prevSong();
		player->setSource(m_playList_song.currentUrl());
		ui->resultsList->setCurrentRow(m_playList_song.currentIndex());

		player->play();

	}
	


}
		//播放按钮：											over
void Mainwindow::on_playBtn_released()
{
	//qInfo() << "播放按钮按下";

	if (QMediaPlayer::PlaybackState::PlayingState == player->playbackState())
	{
		ui->playBtn->setText("pause/stop");
		player->pause();
	}
	else if (QMediaPlayer::PlaybackState::PausedState == player->playbackState())
	{
		ui->playBtn->setText("play");
		player->play();
	}
	else if (QMediaPlayer::PlaybackState::StoppedState == player->playbackState())
	{
		ui->playBtn->setText("play");
		player->play();
	}
	
}
		//下一曲按钮：										over
void Mainwindow::on_nextBtn_released()
{
	//qInfo() << "下一首按钮按下";


	if (!isLocal || isHistory)				//历史音乐
	{
		row++;
		if (row >= ui->history->count())
		{
			row = 0;

		}

		//查询搜索数据库历史记录表当中存储音乐数据信息：
		QSqlQuery query;
		QString sql = QString("select * from historysong where id = %1;").arg(row + 1);
		if (!query.exec(sql))
		{
			QMessageBox::critical(0, QObject::tr("select * from history row Error."), database.lastError().text());

		}


		QString album_id, hash;
		while (query.next())
		{
			QSqlRecord record = query.record();

			int album_idkey = record.indexOf("album_id");
			int hashkey = record.indexOf("hash");


			album_id = query.value(album_idkey).toString();
			hash = query.value(hashkey).toString();
		}

		downloadSong(album_id, hash);
	}
	else
	{
		m_playList_song.nextSong();
		player->setSource(m_playList_song.currentUrl());
		ui->resultsList->setCurrentRow(m_playList_song.currentIndex());

		player->play();
	}
	
}
		//循环按钮：											over
void Mainwindow::on_loopBtn_released()
{
	//qInfo() << "循环按钮按下";
#if 0		//测试时，删除historysong 操作：
	QSqlQuery query;

	QString sql = QString("drop table historysong;");
	if (!query.exec(sql))
	{
		qInfo() << "shibaile";
	}
#endif

	if (!isLoop)
	{
		ui->loopBtn->setText("Start the loop");
		isLoop = true;
	}
	else
	{
		ui->loopBtn->setText("Close the loop");
		isLoop = false;
	}


}




//本地音乐初始化：												over
void Mainwindow::local_music_init()
{
	auto path = "assets/music";
	QDir dir(path);

	auto list = dir.entryList(QStringList() << "*.mp3" << "*.ncm");
	if (list.isEmpty())
	{
		QMessageBox::critical(0, QObject::tr("open local music Error."), database.lastError().text());
		return;
	}

	for (auto str : list)
	{
		QString pathname = "assets/music/" + str;
		qInfo() << QUrl::fromLocalFile(pathname);

		//把媒体文件路径保存到播放列表：
		m_playList_song.addUrl(QUrl::fromLocalFile(pathname));
	}

	ui->resultsList->addItems(list);

}




//绘图事件响应函数												over
void Mainwindow::paintEvent(QPaintEvent* ev)
{
	QPainter painter(this);


	painter.drawPixmap(0, 0, width(), height(), QPixmap("./assets/images/back.jpg"));
}


//用来处理播放器的顺序播放：
void Mainwindow::mousePressEvent(QMouseEvent* ev)
{
	//算了 先不实现了；

	//if (ui->resultsList->geometry().contains(ev->pos() ))
	//{
	//	isResults = true;
	//}
	//
	//else if (ui->history->geometry().contains(ev->pos()))
	//{
	//	isHistory = true;
	//}

	//qInfo() << "isResults>" << isResults << " isHistory>" << isHistory;

}

//事件过滤函数：这是searchEdit的时间过滤函数，用来输入完数据之后，快速搜索音乐；
bool Mainwindow::eventFilter(QObject* obj, QEvent* ev)
{
	//如果目标是	该输入框：
	if (obj = ui->searchEdit)
	{
		//如果事件响应是总事件的键盘按下：
		if (ev->type() == QEvent::KeyRelease)
		{
			//类型转换：把QEvent*		转换成QKeyEcent* 类型，用来处理键盘事件响应；		用智能指针来处理，方便释放内存；
			QKeyEvent* keyEvent = static_cast<QKeyEvent*>(ev);
			//如果按下的键盘的键位是return/enter	：
			if (keyEvent->key() == Qt::Key::Key_Return)
			{
				//qInfo() << 1;

				//模拟按钮按下：
				ui->searchBtn->click();

			}

		}

	}


	return false;
}
